<script>
import {
  GlFormGroup,
  GlFormInput,
  GlDropdown,
  GlDropdownItem,
  GlFormRadio,
  GlFormRadioGroup,
} from '@gitlab/ui';
import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue';
import { VULNERABILITY_STATE_OBJECTS } from 'ee/vulnerabilities/constants';
import { SEVERITY_LEVELS, DETECTION_METHODS } from 'ee/security_dashboard/store/constants';
import { s__, __ } from '~/locale';
import * as i18n from './i18n';

export default {
  components: {
    GlFormGroup,
    GlFormInput,
    GlDropdown,
    GlDropdownItem,
    GlFormRadio,
    GlFormRadioGroup,
    SeverityBadge,
  },
  props: {
    validationState: {
      type: Object,
      required: false,
      default: () => ({}),
    },
  },
  data() {
    return {
      // Note: The cvss field is disabled during the MVC because the backend implementation
      // is still missing. Since I learned this after implementing the design, I decided to
      // hide it from the UI until the backend is ready so that we don't lose the work
      // already completed.
      showCvss: false,
      cvss: '',
      statusId: '',
      severity: '',
      detectionMethod: -1,
      severityState: null,
      statusState: null,
    };
  },
  computed: {
    selectedSeverity() {
      return this.severityOptions.find(({ id }) => id === this.severity);
    },
    severityPlaceholder() {
      return this.selectedSeverity?.name || this.$options.i18n.severity.placeholder;
    },
    cvssDescription() {
      const scores = this.$options.cvss[this.selectedSeverity?.id];

      if (!scores) {
        return '';
      }

      return `${this.selectedSeverity.name}: ${scores[0].toFixed(1)} - ${scores[1].toFixed(1)}`;
    },
    detectionMethodPlaceholder() {
      return (
        this.detectionMethodOptions.find(({ id }) => id === this.detectionMethod)?.name ||
        this.$options.i18n.detectionMethod.placeholder
      );
    },
    detectionMethodOptions() {
      return Object.entries(DETECTION_METHODS).map(([id, name]) => ({ id, name }));
    },
    severityOptions() {
      return Object.entries(SEVERITY_LEVELS).map(([id, name]) => ({ id, name }));
    },
    statusOptions() {
      return [
        { ...VULNERABILITY_STATE_OBJECTS.detected },
        { ...VULNERABILITY_STATE_OBJECTS.confirmed },
        { ...VULNERABILITY_STATE_OBJECTS.resolved },
      ];
    },
  },
  methods: {
    selectSeverity(value) {
      this.severity = value;
      this.emitChanges();
    },

    selectDetectionMethod(value) {
      this.detectionMethod = value;
      this.emitChanges();
    },

    emitChanges() {
      this.$emit('change', {
        status: this.statusId,
        severity: this.severity,
        detectionMethod: this.detectionMethod,
      });
    },
  },
  cvss: {
    none: [0, 0],
    low: [0.1, 3.9],
    medium: [4.0, 6.9],
    high: [7.0, 8.9],
    critical: [9.0, 10.0],
  },
  i18n: {
    errorSeverity: i18n.ERROR_SEVERITY,
    errorStatus: i18n.ERROR_STATUS,
    title: s__('Vulnerability|Details'),
    description: s__(
      'Vulnerability|Information related to how the vulnerability was discovered and its impact on the system.',
    ),
    detectionMethod: {
      label: s__('Vulnerability|Detection method'),
      placeholder: s__('VulnerabilityManagement|Select a method'),
    },
    severity: {
      label: s__('Vulnerability|Severity'),
      placeholder: s__('Vulnerability|Select a severity'),
    },
    cvssLabel: s__('Vulnerability|CVSS v3'),
    optional: __('Optional'),
    status: {
      label: __('Status'),
      description: s__(
        'Vulnerability|Set the status of the vulnerability finding based on the information available to you.',
      ),
    },
  },
};
</script>

<template>
  <section>
    <header class="gl-pt-4 gl-my-6 gl-border-t-gray-100 gl-border-t-solid gl-border-t-1">
      <h3 class="gl-mt-0 gl-mb-3">
        {{ $options.i18n.title }}
      </h3>
      <p data-testid="section-description">
        {{ $options.i18n.description }}
      </p>
    </header>
    <gl-form-group
      :label="$options.i18n.detectionMethod.label"
      label-for="form-detection-method"
      class="gl-mb-6 gl-display-none"
    >
      <gl-dropdown id="form-detection-method" :text="detectionMethodPlaceholder">
        <gl-dropdown-item
          v-for="scanner in detectionMethodOptions"
          :key="scanner.id"
          is-check-item
          :is-checked="detectionMethod === scanner.id"
          @click="selectDetectionMethod(scanner.id)"
        >
          {{ scanner.name }}
        </gl-dropdown-item>
      </gl-dropdown>
    </gl-form-group>
    <div class="gl-display-flex gl-mb-6">
      <gl-form-group
        :label="$options.i18n.severity.label"
        :state="validationState.severity"
        :invalid-feedback="$options.i18n.errorSeverity"
        label-for="form-severity"
        class="gl-mr-6 gl-mb-0"
      >
        <gl-dropdown id="form-severity" :text="severityPlaceholder">
          <gl-dropdown-item
            v-for="{ id } in severityOptions"
            :key="id"
            :is-checked="severity === id"
            is-check-item
            @click="selectSeverity(id)"
          >
            <severity-badge :severity="id" />
          </gl-dropdown-item>
        </gl-dropdown>
      </gl-form-group>
      <gl-form-group v-if="showCvss" :description="cvssDescription" class="gl-mb-0">
        <label for="form-cvss" class="gl-display-block gl-mb-2"
          >{{ $options.i18n.cvssLabel }}
          <span class="gl-font-weight-300">({{ $options.i18n.optional }})</span></label
        >
        <gl-form-input id="form-cvss" v-model="cvss" class="gl-mb-2" type="text" />
      </gl-form-group>
    </div>
    <gl-form-group
      :label="$options.i18n.status.label"
      :state="validationState.status"
      :invalid-feedback="$options.i18n.errorStatus"
    >
      <p>{{ $options.i18n.status.description }}</p>
      <gl-form-radio-group :checked="statusId" @change="emitChanges">
        <label
          v-for="status in statusOptions"
          :key="status.state"
          class="gl-display-flex gl-mb-5 gl-font-weight-normal gl-overflow-break-word"
        >
          <gl-form-radio v-model="statusId" :value="status.state">
            {{ status.buttonText }}
            <template #help>
              <span class="gl-text-gray-500">{{ status.description }}</span>
            </template>
          </gl-form-radio>
        </label>
      </gl-form-radio-group>
    </gl-form-group>
  </section>
</template>
